package fm.service.impl;

import fm.cache.ConfigCache;
import fm.dao.HibernateBaseDao;
import fm.dto.ActivityAndFlows;
import fm.entity.Activity;
import fm.entity.ActivityFlow;
import fm.entity.Flow;
import fm.entity.PublicNumber;
import fm.entityEnum.ActivityStatus;
import fm.entityEnum.Carrier;
import fm.exception.BizException;
import fm.service.ActivityAndFlowsService;
import fm.util.CommonUtils;
import fm.util.Constant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.*;

/**
 * Created by 宏炜 on 2016-03-07.
 */
@Service
public class ActivityAndFlowsServiceImpl implements ActivityAndFlowsService {

    @Autowired
    HibernateBaseDao baseDao;

    @Override
    public Map addActivityAndFlows(ActivityAndFlows activityAndFlows) throws BizException {
        if (CommonUtils.isEmpty(activityAndFlows)) {
            throw new BizException("新增活动数据不能为空");
        }
        Activity activity = activityAndFlows.getActivity();
        List<ActivityFlow> flows = activityAndFlows.getFlows();
        if (CommonUtils.isEmpty(activity)) {
            throw new BizException("基础信息不能为空");
        }
        if (CommonUtils.isEmpty(activity.getTitle())) {
            throw new BizException("活动名称不能为空");
        }
        if (CommonUtils.isEmpty(activity.getStartTime())) {
            throw new BizException("活动开始时间不能为空");
        }
        if (CommonUtils.isEmpty(activity.getEndTime())) {
            throw new BizException("活动结束时间不能为空");
        }
        if (activity.getStartTime().compareTo(activity.getEndTime()) > 0) {
            throw new BizException("活动开始时间不能晚于活动结束时间");
        }
        if (CommonUtils.isEmpty(activity.getCount())) {
            throw new BizException("活动奖品数量不能为空");
        }
        if (CommonUtils.isEmpty(activity.getDescription())) {
            throw new BizException("活动描述不能为空");
        }
        if (CommonUtils.isEmpty(activity.getRule())) {
            throw new BizException("活动规则不能为空");
        }
        if (CommonUtils.isEmpty(activity.getLogoUrl())) {
            throw new BizException("活动Logo不能为空");
        }
        if (CommonUtils.isEmpty(flows)) {
            throw new BizException("至少需要添加一个奖品");
        }
        if (flows.size() == 0) {
            throw new BizException("至少需要添加一个奖品");
        }
        Integer yidong = 0;
        Integer liantong = 0;
        Integer dianxin = 0;
        for (ActivityFlow activityFlow : flows) {
            if (CommonUtils.isEmpty(activityFlow.getFlow())) {
                throw new BizException("流量包配置不能为空");
            }
            if (CommonUtils.isEmpty(activityFlow.getProbability()) || activityFlow.getProbability() == 0) {
                throw new BizException("奖品中奖概率不能为空或为0");
            }
            Flow flow = getFlow(activityFlow.getFlow().getId());
            if (flow.getCarrier().equals(Carrier.YIDONG)) {
                yidong += activityFlow.getProbability();
            }
            if (flow.getCarrier().equals(Carrier.LIANTONG)) {
                liantong += activityFlow.getProbability();
            }
            if (flow.getCarrier().equals(Carrier.DIANXIN)) {
                dianxin += activityFlow.getProbability();
            }
        }
        if (yidong > 100) {
            throw new BizException("移动流量包奖品的中奖概率总和不能大于100%");
        }
        if (liantong > 100) {
            throw new BizException("联通流量包奖品的中奖概率总和不能大于100%");
        }
        if (dianxin > 100) {
            throw new BizException("电信流量包奖品的中奖概率总和不能大于100%");
        }
        Timestamp currentTime = new Timestamp(new Date().getTime());
        if (currentTime.compareTo(activity.getStartTime()) < 0) {
            activity.setStatus(ActivityStatus.NOSTARTED);
        }
        if (currentTime.compareTo(activity.getEndTime()) > 0) {
            activity.setStatus(ActivityStatus.OVERDUE);
        }
        if (currentTime.compareTo(activity.getStartTime()) > 0 && currentTime.compareTo(activity.getEndTime()) < 0) {
            activity.setStatus(ActivityStatus.PROCESS);
        }
        activity.setProbability(100);
        activity.setTimes(1);
        activity.setRemainCount(activity.getCount());
        activity.setCreateTime(new Timestamp(new Date().getTime()));
        baseDao.save(activity);
        PublicNumber publicNumber = (PublicNumber) baseDao.getAll(PublicNumber.class).get(0);
        activity.setLink(ConfigCache.getConfig("SERVICE_URL") + "/activity/flow/" + activity.getId() + "?uuid=" + publicNumber.getUuid());
        activity.setExchangeLink(ConfigCache.getConfig("SERVICE_URL") + "/market/flow/exchange/" + activity.getId() + "?uuid=" + publicNumber.getUuid());
        baseDao.merge(activity);
        addFlows(flows, activity);
        Map<String, Object> result = new HashMap<>();
        result.put("title", activity.getTitle());
        result.put("status", activity.getStatus().getDesc());
        result.put("startTime", activity.getStartTime());
        result.put("endTime", activity.getEndTime());
        result.put("probability", activity.getProbability());
        result.put("count", activity.getCount());
        result.put("remainCount", activity.getRemainCount());
        result.put("times", activity.getTimes());
        result.put("description", activity.getDescription());
        result.put("link", activity.getLink());
        result.put("createTime", activity.getCreateTime());
        result.put("rule", activity.getRule());
        result.put("logoUrl", activity.getLogoUrl());
        result.put("id", activity.getId());
        result.put("version", activity.getVersion());
        result.put("exchangeLink", activity.getExchangeLink());
        return result;
    }

    @Override
    public Integer addFlows(List<ActivityFlow> activityFlowList, Activity activity) {
        Integer res = 0;
        for (ActivityFlow activityFlow : activityFlowList) {
            activityFlow.setActivity(activity);
            baseDao.save(activityFlow);
            res++;
        }
        return res;
    }

    @Override
    public Map updateActivityAndFlows(ActivityAndFlows activityAndFlows) throws BizException {
        if (CommonUtils.isEmpty(activityAndFlows)) {
            throw new BizException("修改活动数据不能为空");
        }
        Activity activity = activityAndFlows.getActivity();
        List<ActivityFlow> flows = activityAndFlows.getFlows();
        if (CommonUtils.isEmpty(activity)) {
            throw new BizException("基础信息不能为空");
        }
        Activity activityTmp = getActivity(activity.getId());
        String hql = "from ActivityFlow where activity = ?";
        List<ActivityFlow> activityFlowList = (List<ActivityFlow>) baseDao.queryForList(hql, activityTmp);
        if (CommonUtils.isEmpty(activityTmp)) {
            throw new BizException("请求修改的活动不存在");
        }
        Timestamp currentTime = new Timestamp(new Date().getTime());
        if (currentTime.compareTo(activityTmp.getEndTime()) > 0) {
            throw new BizException("活动已结束，无法修改");
        }
//        if(currentTime.compareTo(activityTmp.getStartTime()) > 0 && currentTime.compareTo(activityTmp.getEndTime()) < 0){
//            if(!CommonUtils.isEmpty(activity.getStartTime()) || !CommonUtils.isEmpty(activity.getEndTime()) || flows.size() > 0){
//                throw new BizException("活动正在进行中，无法修改(开始时间、停止时间、中奖概率)");
//            }
//        }

        if (currentTime.compareTo(activityTmp.getStartTime()) < 0) {
            if (!CommonUtils.isEmpty(activity.getStartTime())) {
                activityTmp.setStartTime(activity.getStartTime());
            }
            if (!CommonUtils.isEmpty(activity.getEndTime())) {
                activityTmp.setEndTime(activity.getEndTime());
            }
            if (CommonUtils.isEmpty(flows)) {
                throw new BizException("至少需要添加一个奖品");
            }
            if (flows.size() == 0) {
                throw new BizException("至少需要添加一个奖品");
            }
        }
        if (!CommonUtils.isEmpty(activity.getTitle())) {
            activityTmp.setTitle(activity.getTitle());
        }
        if (!CommonUtils.isEmpty(activity.getRule())) {
            activityTmp.setRule(activity.getRule());
        }
        if (!CommonUtils.isEmpty(activity.getLogoUrl())) {
            activityTmp.setLogoUrl(activity.getLogoUrl());
        }

        if (activityTmp.getStartTime().compareTo(activityTmp.getEndTime()) > 0) {
            throw new BizException("活动开始时间不能晚于活动结束时间");
        }

        Integer yidong = 0;
        Integer liantong = 0;
        Integer dianxin = 0;
        for (ActivityFlow activityFlow : flows) {
            if (CommonUtils.isEmpty(activityFlow.getFlow())) {
                throw new BizException("流量包配置不能为空");
            }
            if (CommonUtils.isEmpty(activityFlow.getProbability()) || activityFlow.getProbability() == 0) {
                throw new BizException("奖品中奖概率不能为空或为0");
            }
            Flow flow = getFlow(activityFlow.getFlow().getId());
            if (flow.getCarrier().equals(Carrier.YIDONG)) {
                yidong += activityFlow.getProbability();
            }
            if (flow.getCarrier().equals(Carrier.LIANTONG)) {
                liantong += activityFlow.getProbability();
            }
            if (flow.getCarrier().equals(Carrier.DIANXIN)) {
                dianxin += activityFlow.getProbability();
            }
        }
        if (yidong > 100) {
            throw new BizException("移动流量包奖品的中奖概率总和不能大于100%");
        }
        if (liantong > 100) {
            throw new BizException("联通流量包奖品的中奖概率总和不能大于100%");
        }
        if (dianxin > 100) {
            throw new BizException("电信流量包奖品的中奖概率总和不能大于100%");
        }
        if (currentTime.compareTo(activityTmp.getStartTime()) < 0) {
            activityTmp.setStatus(ActivityStatus.NOSTARTED);
        }
        if (currentTime.compareTo(activityTmp.getEndTime()) > 0) {
            activityTmp.setStatus(ActivityStatus.OVERDUE);
        }
        if (currentTime.compareTo(activityTmp.getStartTime()) > 0 && currentTime.compareTo(activityTmp.getEndTime()) < 0) {
            activityTmp.setStatus(ActivityStatus.PROCESS);
        }

        baseDao.update(activityTmp);

        for (ActivityFlow activityFlow : activityFlowList) {
            baseDao.delete(activityFlow);
        }
        addFlows(flows, activityTmp);
        PublicNumber publicNumber = (PublicNumber) baseDao.getAll(PublicNumber.class).get(0);
        activityTmp.setExchangeLink(ConfigCache.getConfig("SERVICE_URL") + "/market/flow/exchange/" + activity.getId() + "?uuid=" + publicNumber.getUuid());
        Map<String, Object> result = new HashMap<>();
        result.put("title", activityTmp.getTitle());
        result.put("status", activityTmp.getStatus().getDesc());
        result.put("startTime", activityTmp.getStartTime());
        result.put("endTime", activityTmp.getEndTime());
        result.put("probability", activityTmp.getProbability());
        result.put("count", activityTmp.getCount());
        result.put("remainCount", activityTmp.getRemainCount());
        result.put("times", activityTmp.getTimes());
        result.put("description", activityTmp.getDescription());
        result.put("link", activityTmp.getLink());
        result.put("createTime", activityTmp.getCreateTime());
        result.put("rule", activityTmp.getRule());
        result.put("logoUrl", activityTmp.getLogoUrl());
        result.put("id", activityTmp.getId());
        result.put("version", activityTmp.getVersion());
        result.put("exchangeLink", activityTmp.getExchangeLink());
        return result;
    }

    @Override
    public Activity getActivity(Long id) throws BizException {
        if (CommonUtils.isEmpty(id)) {
            return null;
        }
        Activity activity = (Activity) baseDao.getById(Activity.class, id);
        return activity;
    }

    @Override
    public void deleteActivity(Long id) throws BizException {
        Activity activityTmp = getActivity(id);
        if (CommonUtils.isEmpty(activityTmp)) {
            throw new BizException("请求删除的活动不存在");
        }
        Timestamp currentTime = new Timestamp(new Date().getTime());
        if (currentTime.compareTo(activityTmp.getStartTime()) > 0 && currentTime.compareTo(activityTmp.getEndTime()) < 0) {
            throw new BizException("活动正在进行中，无法删除");
        }
        if (currentTime.compareTo(activityTmp.getEndTime()) > 0) {
            throw new BizException("活动已结束归档，无法删除");
        }
        activityTmp.setStatus(ActivityStatus.DELETED);
    }

    @Override
    public List getActivityList(Integer page, Integer size) throws BizException {
        String hql = "from Activity a where a.status != ? order by id desc";
        List<Activity> list = (List<Activity>) baseDao.pageQuery(hql, page, size, ActivityStatus.DELETED);
        List<Map> resutlist = new ArrayList<>();
        for (Activity activity : list) {
            activity.setExchangeLink(ConfigCache.getConfig("SERVICE_URL") + "/market/flow/exchange/" + activity.getId());
            Map<String, Object> result = new HashMap<>();
            result.put("title", activity.getTitle());
            result.put("status", activity.getStatus().getDesc());
            result.put("startTime", activity.getStartTime());
            result.put("endTime", activity.getEndTime());
            result.put("probability", activity.getProbability());
            result.put("count", activity.getCount());
            result.put("remainCount", activity.getRemainCount());
            result.put("times", activity.getTimes());
            result.put("description", activity.getDescription());
            result.put("link", activity.getLink());
            result.put("createTime", activity.getCreateTime());
            result.put("rule", activity.getRule());
            result.put("logoUrl", activity.getLogoUrl());
            result.put("id", activity.getId());
            result.put("version", activity.getVersion());
            result.put("exchangeLink", activity.getExchangeLink());
            resutlist.add(result);
        }
        return resutlist;
    }

    @Override
    public Long getActivityCount() throws BizException {
        String hql = "select count(id) from Activity a where a.status != ?";
        return (Long) baseDao.getUnique(hql, ActivityStatus.DELETED);
    }

    @Override
    public List getActivityFlowList(Long activityId) throws BizException {
        String hql = "from ActivityFlow where activity = ?";
        List<Map> resList = new ArrayList<>();
        List<ActivityFlow> activityFlowList = (List<ActivityFlow>) baseDao.queryForList(hql, getActivity(activityId));
        for (ActivityFlow activityFlow : activityFlowList) {
            Map<String, Object> flow = new HashMap<>();
            flow.put("probability", activityFlow.getProbability());
            flow.put("flowId", activityFlow.getFlow().getId());
            flow.put("sn", activityFlow.getFlow().getSn());
            flow.put("carrierPrice", activityFlow.getFlow().getCarrierPrice());
            flow.put("discount", activityFlow.getFlow().getDiscount());
            flow.put("capacity", activityFlow.getFlow().getCapacity());
            flow.put("carrier", activityFlow.getFlow().getCarrier());
            flow.put("name", activityFlow.getFlow().getName());
            resList.add(flow);
        }
        return resList;
    }

    @Override
    public Long getActivityFlowCount(Long activityId) throws BizException {
        String hql = "select count(id) from ActivityFlow where activity = ?";
        return (Long) baseDao.getUnique(hql, getActivity(activityId));
    }

    @Override
    public List<Activity> getAllActivity() {
        return (List<Activity>) baseDao.getAll(Activity.class);
    }

    @Override
    public void updateActivityStatus(Activity activity) {
        if (CommonUtils.isEmpty(activity)) {
            return;
        }
        Timestamp currentTime = new Timestamp(new Date().getTime());
        if (currentTime.compareTo(activity.getStartTime()) < 0) {
            activity.setStatus(ActivityStatus.NOSTARTED);
        }
        if (currentTime.compareTo(activity.getEndTime()) > 0) {
            activity.setStatus(ActivityStatus.OVERDUE);
        }
        if (currentTime.compareTo(activity.getStartTime()) > 0 && currentTime.compareTo(activity.getEndTime()) < 0) {
            activity.setStatus(ActivityStatus.PROCESS);
        }
        baseDao.update(activity);
    }

    @Override
    public Flow getFlow(Long id) {
        if (CommonUtils.isEmpty(id)) {
            return null;
        }
        return (Flow) baseDao.getById(Flow.class, id);
    }
}
